/*
 * Albareth - an action roleplaying game.
 * Copyright (C) 2008 Jens Anuth
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 *   02110-1301, USA.
 * 
 * $Id: UIManager.java 44 2008-05-14 18:22:13Z jens464 $
*/
package albareth.frontend.slick.ui;

import org.lwjgl.input.Cursor;
import org.newdawn.slick.Font;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;

import albareth.frontend.slick.SlickResources;
import frosch.util.Log;

public final class UIManager extends UIElement
{
    public static Cursor DEFAULT_MOUSE_CURSOR = SlickResources.CURSOR_DEFAULT;
    public static final int DOUBLE_CLICK_DELAY = 500;

    private GameContainer _container;

    private static String _currentTooltipText = "";

    private static int _mouseButtonDown = -1;
    private static int _mouseButtonDownX = -1;
    private static int _mouseButtonDownY = -1;

    private static long _doubleClickStartTime = 0;
    private static int _doubleClickStartX = -1;
    private static int _doubleClickStartY = -1;


    private static DraggeableItem _currentlyDraggedItem = null;
    private static boolean _askedForDrag = false;
    private static int _currentDragStartX = -1;
    private static int _currentDragStartY = -1;

    private static UIElement _currentKeyboardFocusComponent = null;
    



    
    public UIManager(GameContainer container, Font defaultFont)
    {
        super(0, 0, container.getScreenWidth(), container.getScreenHeight());
        _container = container;
        setFont(defaultFont);
        setMouseCursor(DEFAULT_MOUSE_CURSOR);
    }
    
    public static int getMouseButtonDown()
    {
        return _mouseButtonDown;
    }

    
    
    public final void renderUI(Graphics g, GameContainer container) throws SlickException
    {
        processRender(g, null);
        
    }

    public final void updateUI(int delta, GameContainer container) throws SlickException
    {
        processUpdate(delta, container, this);
    }
    
    public void render(Graphics g, GameContainer container, int screenX, int screenY)
            throws SlickException
    {
    }
    
    public boolean processMousePressed(int button, int x, int y)
    {
        _mouseButtonDown = button;
        _mouseButtonDownX = x;
        _mouseButtonDownY = y;
        _askedForDrag = false;
        
        //double click?
        if (button == 0)
        {
            if (System.currentTimeMillis() - _doubleClickStartTime <
                    DOUBLE_CLICK_DELAY && _doubleClickStartX == x &&
                        _doubleClickStartY == y)
            {
                processMouseDoubleClicked(button, x, y);
            } else {
                _doubleClickStartTime = System.currentTimeMillis();
                _doubleClickStartX = x;
                _doubleClickStartY = y;
            }
        }

        return super.processMousePressed(button, x, y);
    }
    
    public boolean processMouseReleased(int button, int x, int y)
    {
        super.processMouseReleased(button, x, y);
        
        _mouseButtonDown = -1;
        
        //perform DROP:
        if (_currentlyDraggedItem != null)
        {
            processMouseDrop(_currentlyDraggedItem, x, y);
            _currentlyDraggedItem = null;
            setMouseCursor(DEFAULT_MOUSE_CURSOR);
        }

        
        //mouse clicked? (released where pressed)
        if (x == _mouseButtonDownX && y == _mouseButtonDownY) {
            processMouseClicked(button, x, y);
        }

        return true;
    }


    /**
     * Updates the ui's current mouse-over tooltip-text.
     */
    public boolean processMouseMoved(int newx, int newy)
    {
        if (_mouseButtonDown == 0)
        {
            if (!_askedForDrag) {
                startMouseDrag(_mouseButtonDown, newx, newy);
                _askedForDrag = true;
            }
            return true;
        }

        _currentTooltipText = getTooltipText(newx, newy);
        
        super.processMouseMoved(newx, newy);
        

        return true;
    }


    private void startMouseDrag(int mouseButtonDown, int x, int y)
    {
        //TODO: isDragAllowed gets not respected yet.
        DraggeableItem item = getDraggeableItem(x, y);

        if (item == null) {
            return;
        }
        
        Image iconImage = item.getIconImage();
        
        if (iconImage != null)
        {
            Cursor iconCursor = UIToolkit.createMouseCursorFromImage(
                    item.getIconImage(), 16, 16, 2
            );
            setMouseCursor(iconCursor);

        }

        _currentlyDraggedItem = item;
        _currentDragStartX = x;
        _currentDragStartY = y;
    }
    
    public boolean processKeyPressed(int key, char c)
    {
        if (_currentKeyboardFocusComponent == null) {
            return false;
        }
        if (key == Input.KEY_ESCAPE) {
            releaseKeyboardFocus(_currentKeyboardFocusComponent);
            return true;
        }
        
        return _currentKeyboardFocusComponent.keyPressed(key, c);
    }


    public boolean processKeyReleased(int key, char c)
    {
        if (_currentKeyboardFocusComponent == null) {
            return false;
        }

        return _currentKeyboardFocusComponent.keyReleased(key, c);
    }

    
    public void setMouseCursor(Cursor cursor)
    {
        try {
            _container.setMouseCursor(cursor, 16, 16);
        } catch (SlickException e) {
            Log.error("Setting mouse cursor failed: " + e);
        }
    }


    /**
     * @return the ui's current mouse-over tooltip-text.
     */
    public static String getCurrentUITooltipText()
    {
        return _currentTooltipText;
    }


    public static DraggeableItem getCurrentlyDraggedItem()
    {
        return _currentlyDraggedItem;
    }

    /*
    public static int getCurrentDragStartX()
    {
        //System.err.println(_currentDragStartX);
        return _currentDragStartX;
    }*/

    /*
    public static int getCurrentDragStartY()
    {
        //System.err.println(_currentDragStartY);
        return _currentDragStartY;
    }*/

    public static void requestKeyboardFocus(UIElement elem)
    {
        elem.setKeyboardFocus(true);
        _currentKeyboardFocusComponent  = elem;
    }
    
    public static void releaseKeyboardFocus(UIElement currentKeyboardFocusComponent)
    {
        if (_currentKeyboardFocusComponent != null) {
            _currentKeyboardFocusComponent.setKeyboardFocus(false);
            _currentKeyboardFocusComponent = null;
        }
    }



}
